package edu.washington.cs.sounddetector.server.sound;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.washington.cs.sounddetector.server.api.object.SoundFormat;
import edu.washington.cs.sounddetector.server.database.DbSoundClass;
import edu.washington.cs.sounddetector.server.database.Sound;

/**
 * A collection of static helper methods for dealing with sound stuff.
 * 
 * @author the.dylan.price@gmail.com
 * 
 */
public class SoundHelper
{
    private static Log log = LogFactory.getLog(SoundHelper.class);

    /**
     * @param soundFormat
     *            a SoundFormat object
     * @return a new AudioFormat object created based on the state of the given soundFormat
     */
    public static AudioFormat convert(SoundFormat soundFormat)
    {
        AudioFormat format = new AudioFormat(soundFormat.getSampleRate(),
                soundFormat.getSampleSizeInBits(), soundFormat.getChannels(),
                soundFormat.isSigned(), soundFormat.isBigEndian());
        return format;
    }

    public static List<Sound> getRandomNoises(SoundProcessorBuilder spb,
            DbSoundClass unknownSoundClass)
    {
        List<Sound> sounds = new ArrayList<Sound>();
        SoundProcessor sp = spb.build();
        for (Noise noise : Noise.values())
        {
            try
            {
                InputStream in = SoundHelper.class.getResourceAsStream(
                        noise.getPath());
                AudioInputStream stream = AudioSystem.getAudioInputStream(in);
                double[] samples = sp.sample(stream, stream.getFormat());
                SoundFeatures features = sp.extractFeatures(samples);
                Sound sound = new Sound(unknownSoundClass, null, samples,
                        features.getFlattenedFeatureValues());
                sounds.add(sound);
            }
            catch (Exception e)
            {
                log.error("Could not retrieve noise " + noise, e);
            }
        }

        return sounds;
    }

    private enum Noise
    {
        N1("/noise/soundfile.wav"),
        N2("/noise/soundfile1.wav"),
        N3("/noise/soundfile2.wav"),
        N4("/noise/soundfile3.wav"),
        N5("/noise/soundfile4.wav");

        private String path;

        private Noise(String path)
        {
            this.path = path;
        }

        public String getPath()
        {
            return path;
        }
    }
}
